﻿using BarrageGameAssistant.Core.Configs;
using BarrageGameAssistant.Core.Model;
using NLog;
using BarrageGameAssistant.Core.Extensions;
using System.Drawing.Imaging;
using BarrageGameAssistant.Core.Enums;
using ImageProcess;

namespace BarrageGameAssistant.UIForms
{
    public partial class FrmSceneEditor : Form
    {
        #region 基础属性
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();
        private int _drawMode = 0; //绘图模式
        private bool _reSelectFlag; //重新选择坐标

        /// <summary>
        /// 许可证信息
        /// </summary>
        public Licence? Licence;

        /// <summary>
        /// 程序配置
        /// </summary>
        public Settings? Settings { get; set; }

        /// <summary>
        /// 游戏配置
        /// </summary>
        public GameProject? CurrentGame { get; set; }

        /// <summary>
        /// 场景信息
        /// </summary>
        public Scene? Scene { get; set; }

        /// <summary>
        /// 场景尺寸
        /// </summary>
        public Size SceneResolutionRatio { get; set; } = new Size(1080, 1920);

        /// <summary>
        /// 图片实际大小
        /// </summary>
        public Size ImageRealResolutionRatio;
        #endregion

        private bool _newSceneFlag = true; //新场景标记



        public FrmSceneEditor()
        {
            InitializeComponent();

            this.DoubleBuffered = true;
        }

        #region 加载退出
        private void FrmSceneEditor_Load(object sender, EventArgs e)
        {
            if (Settings == null)
            {
                MessageBox.Show(this, $"全局参数未设置", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            this.cbbPreProcessingMode.SelectedIndex = 0;
            this.capturePictureBox1.FixDisplayPixel = Settings.CaptureFixDisplayPixel;

            SceneResolutionRatio = Settings.DefaultResolutionRatioSize;
            this.cbbSceneType.SelectedIndex = 0;
            this.txtResolutionRatio.Text = $"{SceneResolutionRatio.Width}x{SceneResolutionRatio.Height}";
            this.cbbModeSelection.DataSource = CurrentGame?.ModeSelections;
            this.cbbModeSelection.DisplayMember = "Name";
            this.cbbModeSelection.ValueMember = "Id";


            if (Scene == null)
            {
                _newSceneFlag = true;
                Scene = new Scene
                {
                    Name = $"场景_{CurrentGame?.Scenes.Count + 1}"
                };
                this.txtName.Text = Scene.Name;

                this.capturePictureBox1.SetSize(this.SceneResolutionRatio);
            }
            else
            {
                _newSceneFlag = false;
                this.txtName.Text = Scene.Name;
                this.txtResolutionRatio.Text = $"{Scene.SceneResolutionRatio.Width}x{Scene.SceneResolutionRatio.Height}";
                this.txtImageSize.Text = $"{Scene.ImageRealResolutionRatio.Width}x{Scene.ImageRealResolutionRatio.Height}";
                this.cbbSceneType.SelectedIndex = (int)Scene.SceneType;
                this.nudThreshold.Value = Convert.ToDecimal(Scene.Threshold);
                this.nudStopDuration.Value = Scene.StopDuration;

                foreach (var item in Scene.SceneMatchDatas)
                {
                    ListViewItem lvi = lvSceneMatchDatas.Items.Add((lvSceneMatchDatas.Items.Count + 1).ToString());
                    lvi.Tag = item;
                    lvi.SubItems.Add(item.MatchType.ToDesc());
                    lvi.SubItems.Add(item.ToString());
                }

                this.capturePictureBox1.SetSize(this.ImageRealResolutionRatio);
            }
        }

        private void FrmSceneEditor_Shown(object sender, EventArgs e)
        {

        }

        private void FrmSceneEditor_FormClosing(object sender, FormClosingEventArgs e)
        {

        }

        private void FrmSceneEditor_FormClosed(object sender, FormClosedEventArgs e)
        {
        }
        #endregion

        private void btnCapture_Click(object sender, EventArgs e)
        {
            if (Settings == null) return;
            if (CurrentGame == null) return;
            if (Scene == null) return;

            if (!CurrentGame.IsRunning())
            {
                MessageBox.Show(this, $"游戏没启动,请启动游戏: {CurrentGame.GetPlatformName()}{CurrentGame.Name}", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (CurrentGame.IsCropImage)
            {
                if (CurrentGame.CropImageSize == Size.Empty || CurrentGame.CropImageSize.Width > this.SceneResolutionRatio.Width || CurrentGame.CropImageSize.Height > this.SceneResolutionRatio.Height)
                {
                    MessageBox.Show(this, $"请设置正确的裁剪尺寸.", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }

            //先将将游戏设置为指定的尺寸并置顶获得焦点,最后再截图

            CurrentGame.SetAutoGameWindowNormal(true); //设置窗体正常化
            Thread.Sleep(100);
            CurrentGame.SetAutoGameForeground(true); //窗体前置
            Thread.Sleep(100);
            CurrentGame.SetAutoGameFocus(true); //聚焦窗体
            Thread.Sleep(100);
            CurrentGame.SetGameBounds(Settings.DefaultResolutionRatioSize, false); //设置窗体大小

            var sceneDir = Scene.CurrentDirectory(CurrentGame);
            var sceneImageFile = Path.Combine(sceneDir, $"{Scene?.Id}.png");
            if (File.Exists(sceneImageFile))
            {
                File.Delete(sceneImageFile);
            }

            Bitmap? img = CurrentGame.Capture(this.SceneResolutionRatio.Width) as Bitmap;
            if (img == null)
            {
                MessageBox.Show(this, $"截图失败.", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            else
            {
                if (Scene != null && CurrentGame.IsCropImage)
                    img = ImageHelper.Crop(img, new Rectangle(CurrentGame.CropImageLocation, CurrentGame.CropImageSize));

                if (img != null)
                {
                    //生成原图
                    img.Save(sceneImageFile, ImageFormat.Png);

                    //生成HSV图
                    var hsvFile = Path.Combine(sceneDir, $"{Scene?.Id}_hsv.png");
                    OpenCVHelper.GetHSVImage(img)?.Save(hsvFile);

                    //生成灰度图
                    var grayFile = Path.Combine(sceneDir, $"{Scene?.Id}_gray.png");
                    OpenCVHelper.GetGrayImage(img)?.Save(grayFile);

                    //生成二值化图
                    var binaryFile = Path.Combine(sceneDir, $"{Scene?.Id}_binary.png");
                    OpenCVHelper.GetBinaryImage(img)?.Save(binaryFile);


                    switch (this.cbbPreProcessingMode.SelectedIndex)
                    {
                        case 1:
                            this.capturePictureBox1.SetImage(hsvFile);
                            break;
                        case 2:
                            this.capturePictureBox1.SetImage(grayFile);
                            break;
                        case 3:
                            this.capturePictureBox1.SetImage(binaryFile);
                            break;
                        default:
                            this.capturePictureBox1.SetImage(sceneImageFile);
                            break;
                    }
                    //this.capturePictureBox1.SetImage((Bitmap)img.Clone());
                    ImageRealResolutionRatio = this.capturePictureBox1.Size;

                }
            }
        }

        private void btnCancelReSelect_Click(object sender, EventArgs e)
        {
            _reSelectFlag = false;
            //_reSelectMode = -1;
            this.btnCancelReSelect.Visible = false;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (CurrentGame != null && _newSceneFlag && Scene != null)
            {
                Directory.Delete(Scene.CurrentDirectory(CurrentGame), true);
            }
            this.DialogResult = DialogResult.Cancel;
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            if (Settings == null) return;
            if (CurrentGame == null) return;
            if (Scene == null) return;

            if (string.IsNullOrEmpty(this.txtName.Text.Trim()))
            {
                MessageBox.Show(this, $"场景名称不能为空.", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.txtName.Focus();
                return;
            }

            if (CurrentGame.Scenes.Any(x => x.Name == this.txtName.Text.Trim() && x.Id != Scene.Id))
            {
                MessageBox.Show(this, $"场景名称已存在，请更换场景名称.", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.txtName.Focus();
                return;
            }

            if (_newSceneFlag)
                Scene.Index = this.CurrentGame.Scenes.Count + 1;
            Scene.Name = this.txtName.Text;
            Scene.SceneResolutionRatio = this.SceneResolutionRatio;
            Scene.ImageRealResolutionRatio = this.ImageRealResolutionRatio;
            Scene.SceneType = (GameSceneType)this.cbbSceneType.SelectedIndex;
            Scene.Threshold = Convert.ToDouble(this.nudThreshold.Value);
            Scene.StopDuration = Convert.ToInt32(this.nudStopDuration.Value);

            this.DialogResult = DialogResult.OK;
        }

        #region 图形控件事件
        private void capturePictureBox1_OnPictureSizeChanged(object sender, Size e)
        {
            this.txtImageSize.Text = $"{e.Width}x{e.Height}";
        }

        private void capturePictureBox1_MouseLocation(object sender, Point e)
        {
            Application.DoEvents();
            Invoke((new Action(() =>
            {
                lbMousePoint.Text = $"鼠标坐标：x={e.X}, y={e.Y}";
            })));
        }

        private void capturePictureBox1_SelectedPoint(object sender, Point e)
        {
            if (_drawMode == 2)
            {
                FrmMouseAction frmMouseAction = new();
                frmMouseAction.MouseLocation = e;
                frmMouseAction.MouseAction = null;

                if (frmMouseAction.ShowDialog() == DialogResult.OK)
                {
                    if (frmMouseAction.MouseAction == null) return;

                    Scene?.Actions.Add(frmMouseAction.MouseAction);

                    ListViewItem lvi = lvActions.Items.Add((lvActions.Items.Count + 1).ToString());
                    lvi.Tag = frmMouseAction.MouseAction;
                    lvi.SubItems.Add(frmMouseAction.MouseAction.GetActionType());
                    lvi.SubItems.Add(frmMouseAction.MouseAction.ToString());
                }
            }
        }

        private void capturePictureBox1_SelectedRectangle(object sender, Rectangle e)
        {
            if (Settings == null) return;
            if (CurrentGame == null) return;
            if (Scene == null) return;

            if (_reSelectFlag)
            {
                //重新选择
            }
            else
            {
                if (Licence?.UseEdit == 0)
                {
                    MessageBox.Show(this, $"没有该权限,请升级卡密.", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                try
                {
                    //场景全图
                    string sceneDir = Scene.CurrentDirectory(CurrentGame);
                    var sceneImgFile = Path.Combine(sceneDir, $"{Scene?.Id}.png");
                    //检测文件不存在则执行下面的
                    if (File.Exists(sceneImgFile))
                    {
                        if (_drawMode == 0)
                        {
                            FrmSceneMatchData frmSceneMatchData = new()
                            {
                                Settings = Settings,
                                CurrentGame = CurrentGame,
                                Scene = Scene,
                                MatchData = null,
                                Box = e,
                                PreProcessingMode = this.cbbPreProcessingMode.SelectedIndex
                            };

                            if (frmSceneMatchData.ShowDialog() == DialogResult.OK)
                            {
                                if (frmSceneMatchData.MatchData == null) return;

                                var saveMatchFile = Path.Combine(sceneDir, $"{frmSceneMatchData.MatchData.Id}.png"); //指定保存文件路径
                                using var matchImg = ImageProcess.ImageHelper.Crop(sceneImgFile, frmSceneMatchData.MatchData.Bounds); //区域截图
                                matchImg?.Save(saveMatchFile, ImageFormat.Png); //保存文件

                                frmSceneMatchData.MatchData.SceneSize = SceneResolutionRatio;
                                frmSceneMatchData.MatchData.SceneImageSize = ImageRealResolutionRatio;

                                //添加到场景中的场景识别匹配集合中
                                Scene?.SceneMatchDatas.Add(frmSceneMatchData.MatchData);

                                ListViewItem item = lvSceneMatchDatas.Items.Add((lvSceneMatchDatas.Items.Count + 1).ToString());
                                item.Tag = frmSceneMatchData.MatchData;
                                item.SubItems.Add(frmSceneMatchData.MatchData.MatchType.ToDesc());
                                item.SubItems.Add(frmSceneMatchData.MatchData.ToString());
                            }
                        }
                        else if (_drawMode == 1)
                        {
                            if (this.cbbSceneType.SelectedIndex != 2)
                            {
                                MessageBox.Show(this, $"过程数据源定义只有场景类型为“游戏进行中场景”时使用.", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                return;
                            }

                            FrmProcessMatchData frmProcessMatchData = new()
                            {
                                Settings = Settings,
                                CurrentGame = CurrentGame,
                                Scene = Scene,
                                MatchData = null,
                                Box = e,
                                ProcessMatchDatas = Scene?.ProcessMatchDatas
                            };

                            if (frmProcessMatchData.ShowDialog() == DialogResult.OK)
                            {
                                if (frmProcessMatchData.MatchData == null) return;

                                var saveMatchFile = Path.Combine(sceneDir, $"{frmProcessMatchData.MatchData.Id}.png");
                                using var matchImg = ImageProcess.ImageHelper.Crop(sceneImgFile, frmProcessMatchData.MatchData.Bounds);
                                matchImg?.Save(saveMatchFile, ImageFormat.Png);

                                var rr = this.txtResolutionRatio.Text.Split("x");
                                int w = Convert.ToInt32(rr[0]);
                                int h = Convert.ToInt32(rr[1]);
                                frmProcessMatchData.MatchData.SceneSize = new Size(w, h);

                                //添加到场景中的场景识别匹配集合中
                                Scene?.ProcessMatchDatas.Add(frmProcessMatchData.MatchData);

                                ListViewItem item = lvProcessMatchDatas.Items.Add((lvProcessMatchDatas.Items.Count + 1).ToString());
                                item.Tag = frmProcessMatchData.MatchData;
                                item.SubItems.Add(frmProcessMatchData.MatchData.MatchType.ToDesc());
                                item.SubItems.Add(frmProcessMatchData.MatchData.ToString());
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
        #endregion

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_drawMode != tabControl1.SelectedIndex)
            {
                btnCancelReSelect_Click(this, e);
                _drawMode = tabControl1.SelectedIndex;

                if (_drawMode == 0 || _drawMode == 1)
                {
                    this.capturePictureBox1.DrawCrosshair = true;
                    this.capturePictureBox1.DrawRectangle = true;
                }
                else
                {
                    this.capturePictureBox1.DrawCrosshair = true;
                    this.capturePictureBox1.DrawRectangle = false;
                }
            }
        }

        private void cbbSceneType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbbSceneType.SelectedIndex == 1)
            {
                this.pnlModeSelection.Visible = true;
            }
            else
            {
                this.pnlModeSelection.Visible = false;
            }
        }

        private void btnModeSelection_Click(object sender, EventArgs e)
        {
            FrmEditModeSelection frmEditModeSelection = new FrmEditModeSelection();
            frmEditModeSelection.CurrentGame = CurrentGame;
            if (frmEditModeSelection.ShowDialog() == DialogResult.OK)
            {

            }
        }

        private void cbbPreProcessingMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (Settings == null) return;
            if (CurrentGame == null) return;
            if (Scene == null) return;
            var sceneDir = Scene.CurrentDirectory(CurrentGame);
            string imgPath;
            switch (this.cbbPreProcessingMode.SelectedIndex)
            {
                case 1:
                    imgPath = Path.Combine(sceneDir, $"{Scene?.Id}_hsv.png");
                    this.capturePictureBox1.CrosshairColor = Color.Yellow;
                    this.capturePictureBox1.DrawRectangleColor = Color.Yellow;
                    break;
                case 2:
                    imgPath = Path.Combine(sceneDir, $"{Scene?.Id}_gray.png");
                    this.capturePictureBox1.CrosshairColor = Color.Yellow;
                    this.capturePictureBox1.DrawRectangleColor = Color.Yellow;
                    break;
                case 3:
                    imgPath = Path.Combine(sceneDir, $"{Scene?.Id}_binary.png");
                    this.capturePictureBox1.CrosshairColor = Color.Blue;
                    this.capturePictureBox1.DrawRectangleColor = Color.Blue;
                    break;
                default:
                    imgPath = Path.Combine(sceneDir, $"{Scene?.Id}.png");
                    this.capturePictureBox1.CrosshairColor = Color.Yellow;
                    this.capturePictureBox1.DrawRectangleColor = Color.Yellow;
                    break;
            }
            if (File.Exists(imgPath))
            {
                this.capturePictureBox1.SetImage(imgPath);
                ImageRealResolutionRatio = this.capturePictureBox1.Size;
            }
        }

        private void lvSceneMatchDatas_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (e.IsSelected)
            {
                if (e.Item?.Tag is not SceneMatchData matchData) return;
                this.capturePictureBox1.DrawRectangles?.Clear();
                this.capturePictureBox1.DrawRectangles = [matchData.Bounds];
                this.capturePictureBox1.Refresh();
            }
            else
            {
                this.capturePictureBox1.DrawRectangles?.Clear();
                this.capturePictureBox1.DrawRectangles = [];
                this.capturePictureBox1.Refresh();
            }
        }

        #region 右键菜单
        #region 场景识别定义右键菜单
        private void tsmiEditSceneMatch_Click(object sender, EventArgs e)
        {

        }

        private void tsmiReSelectSceneMatch_Click(object sender, EventArgs e)
        {

        }

        private void tsmiReGenSceneMatchImg_Click(object sender, EventArgs e)
        {

        }

        private void tsmiDelSceneMatch_Click(object sender, EventArgs e)
        {
            if (Licence?.UseEdit == 0)
            {
                MessageBox.Show(this, $"没有该权限,请升级卡密.", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (CurrentGame == null) return;
            if (Scene == null) return;

            if (this.lvSceneMatchDatas.SelectedItems.Count < 1) return;

            if (MessageBox.Show(this, $"是否删除选中项?", "确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                string sceneDir = Scene.CurrentDirectory(CurrentGame);
                foreach (ListViewItem item in this.lvSceneMatchDatas.SelectedItems)
                {
                    SceneMatchData? matchData = item.Tag as SceneMatchData;
                    if (matchData == null) continue;
                    try
                    {
                        this.capturePictureBox1.DrawRectangles?.Remove(matchData.Bounds);

                        var file = Path.Combine(sceneDir, $"{matchData?.Id}.png");
                        File.Delete(file);
                        this.lvSceneMatchDatas.Items.Remove(item);
                        this.Scene.SceneMatchDatas.Remove(matchData);
                    }
                    catch (Exception)
                    {

                    }
                }

                int n = 1;
                foreach (ListViewItem item in this.lvSceneMatchDatas.Items)
                {
                    item.SubItems[0].Text = n++.ToString();
                }
            }
        }
        #endregion

        #region 过程数据源定义右键菜单
        private void tsmiEditProcessMatch_Click(object sender, EventArgs e)
        {

        }

        private void tsmiReSelectProcessMatch_Click(object sender, EventArgs e)
        {

        }

        private void tsmiReGenProcessMatchImg_Click(object sender, EventArgs e)
        {

        }

        private void tsmiDelProcessMatch_Click(object sender, EventArgs e)
        {

        }
        #endregion

        #region 动作右键菜单
        private void tsmiAddKeyboard_Click(object sender, EventArgs e)
        {
            FrmKeyboardAction frmKeyboardAction = new FrmKeyboardAction();
            frmKeyboardAction.KeyboardAction = null;

            if (frmKeyboardAction.ShowDialog() == DialogResult.OK)
            {
                if (frmKeyboardAction.KeyboardAction == null) return;

                Scene?.Actions.Add(frmKeyboardAction.KeyboardAction);

                ListViewItem lvi = lvActions.Items.Add((lvActions.Items.Count + 1).ToString());
                lvi.Tag = frmKeyboardAction.KeyboardAction;
                lvi.SubItems.Add(frmKeyboardAction.KeyboardAction.GetActionType());
                lvi.SubItems.Add(frmKeyboardAction.KeyboardAction.ToString());
            }
        }

        private void tsmiEditAction_Click(object sender, EventArgs e)
        {

        }

        private void tsmiDeleteAction_Click(object sender, EventArgs e)
        {

        }
        #endregion
        #endregion
    }
}
